'''
Subclass of NSBezierPath used to draw, cache, save, and restore drawing information
'''

from AppKit import *
from Foundation import NSInsetRect

print 'DBPath.initializing black'
black = NSColor.blackColor()
print 'DBPath done'

class DBPath(NSBezierPath):

    _lineColor = black
    
    def __new__(cls, *args, **kws):
        return cls.alloc().init()
        
    def newPathFromPath_(cls, pathFrom):
        return DBPath(pathFrom.lineColor(), pathFrom.lineWidth())
    newPathFromPath_ = classmethod(newPathFromPath_)
        
    def __init__(self, lineColor=black, lineWidth=4, moveTo=None, lineTo=None):
        self.setCachesBezierPath_(True)
        self.setLineColor_(lineColor)
        self.setLineWidth_(lineWidth)
        if moveTo:
            self.moveToPoint_(moveTo)
        if lineTo:
            self.lineToPoint_(lineTo)
            
    def __len__(self):
        return self.elementCount()
        
    def __getitem__(self, key):
        return self.elementAtIndex_associatedPoints_(key)
    
    def copyWithColor(self):
        copy = self.copy()
        copy.setLineColor_(self.lineColor())
        return copy
        
    def pop(self):
        elements = [self.elementAtIndex_associatedPoints_(i) for i in range(self.elementCount())]
        self.removeAllPoints()
        for element in elements[0:-1]:
            self.push(element)
        return elements[-1]
                
    def push(self, elementWithPoints):
        type, pts = elementWithPoints        
        if type == NSMoveToBezierPathElement:
            self.moveToPoint_(*pts)
        elif type == NSLineToBezierPathElement:
            self.lineToPoint_(*pts)
        elif type == NSCurveToBezierPathElement:
            self.curveToPoint_controPoint1_controlPoint2_(*pts)
        elif type == NSClosePathBezierPathElement:
            self.closePath()
        
    def equalColorAndWidth(self, path):
        return self.lineColor() == path.lineColor() and self.lineWidth() == path.lineWidth()

    def setLineColor_(self, color):
        self._lineColor = color
        
    def lineColor(self):
        return self._lineColor
            
    def stroke(self):
        self._lineColor.set()
        NSBezierPath.stroke(self)
        
    def bounds(self):
        '''
        Fix buggy bounds() method in NSBezierPath.
        '''
        pts = self.points() # from NSBezierPathExt.py
        if pts:
            all_x = [x for (x,y) in pts]
            all_y = [y for (x,y) in pts]
            x = min(all_x)
            y = min(all_y)
            width = max(all_x) - x
            height = max(all_y) - y
            pad = self.lineWidth() / 2.0
            return NSInsetRect(((x,y),(width,height)), -pad, -pad)
        else:
            return (0,0),(0,0)
        
    def translateXBy_yBy_(self, x, y):
        matrix = NSAffineTransform.transform()
        matrix.translateXBy_yBy_(x,y)
        self.transformUsingAffineTransform_(matrix)
        
    def scaleXBy_yBy_(self, scaleX, scaleY):
        matrix = NSAffineTransform.transform()
        matrix.scaleXBy_yBy_(scaleX, scaleY)
        self.transformUsingAffineTransform_(matrix)
        
    def asString(self):
        # return a list of tuple-ish strings:
        # C color width: create
        # L x y: lineTo x,y
        # M x y: moveTo x,y
        elem_type = {NSMoveToBezierPathElement: 'M',
                     NSLineToBezierPathElement: 'L'}
        elements = ['C %s %d' % (self.lineColor().asString(), self.lineWidth())]
        for i in range(self.elementCount()):
            elem, pts = self.elementAtIndex_associatedPoints_(i)
            elements.append('%s %d %d' % (elem_type[elem], pts[0].x, pts[0].y))
        return '"%s"' % ', '.join(elements)
        
    def asSvg(self, height):
        elem_type = {NSMoveToBezierPathElement: 'M',
                     NSLineToBezierPathElement: 'L'}
        elements = ' '.join(['%s%d %d' % (elem_type[elem], pts[0].x, height - pts[0].y) for elem, pts in self])
        return '<path stroke-width="%d" stroke="%s" d="%s"/>' % (self.lineWidth(), self.lineColor().asSvg(), elements)
    
DBPath.setDefaultLineJoinStyle_(NSRoundLineJoinStyle)
DBPath.setDefaultLineCapStyle_(NSRoundLineCapStyle)
